package fr.univ.colloque.servlet;

import fr.univ.colloque.dao.ColloqueDao;
import fr.univ.colloque.dao.ExposeDao;
import fr.univ.colloque.data.Colloque;
import fr.univ.colloque.data.Etat;
import fr.univ.colloque.data.Expose;
import fr.univ.colloque.data.Personne;
import fr.univ.colloque.util.Link;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class ValiderProgramme extends HttpServlet
{
    // Messages d'erreur

    private static String ERR_CHOIX_ABS = "Vous devez choisir un exposé";
    private static String ERR_DEBUT_ABS = "Vous devez saisir une date de début.";
    private static String ERR_DEBUT_FORMAT = "Mauvais format pour la date de début. (dd/mm/yyyy)";
    private static String ERR_FIN_ABS = "Vous devez saisir une date de fin.";
    private static String ERR_FIN_FORMAT = "Mauvais format pour la date de fin. (dd/mm/yyyy)";
    private static String ERR_FIN_AVANT_DEBUT = "La date de fin doit être postérieur à la date de début.";
    private static final int NOMBRE_EXPOSE_SELECTION = 5;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        HttpSession session = req.getSession();
        
        Link lien = Link.FORM_PROGRAMME_A_VALIDER;
        
        Personne connecte = (Personne) session.getAttribute("user");
        
        if (connecte == null || !lien.getType().equals(connecte.getType()))
        {
            // La personne connecté n'a pas les droits nécessaires pour accéder à cette page
            resp.sendRedirect("indexCo.jsp?e=1");
        }
        else
        {
            
            String idStr = req.getParameter("id");
            
            int id = Integer.parseInt(idStr);
            
            ColloqueDao cDao = new ColloqueDao();
            Colloque co = cDao.get(id, false);
            session.setAttribute("colloque", co);
            
            ExposeDao eDao = new ExposeDao();
            List<Expose> listE = eDao.getExposesColloque(co);
            Collections.sort(listE);
            
            float moyEgalite = -1;
            List<Expose> listExp = new ArrayList<Expose>();
            for (int i = 0; i < listE.size(); i++)
            {
                Expose exp = listE.get(i);
                
                if (i > 4)
                {
                    // Les 5 premiers exposés ( les mieux notés ) sont pris et 
                    // on vérifie qu'il y a pas d'égalité
                    // Si il y a égalité on prend l'exposé
                    int z = i - 1;
                    Expose expPrec = listE.get(z);
                    
                    if (expPrec.getMoyenne() == exp.getMoyenne())
                    {
                        expPrec.setEtat(Etat.ATTENTE);
                        listExp.add(exp);
                        moyEgalite = exp.getMoyenne();
                    }
                    
                }
                else
                {
                    // On prend les 5 premiers exposés
                    exp.setEtat(Etat.ACCEPTE);
                    listExp.add(exp);
                }
            }
            
            for (Expose exp : listE)
            {      
                if (listExp.contains(exp))
                {
                    // Passe en etat "Attente" tous les exposés retenus qui ont 
                    // une moyenne égale à la moyenne "litige"
                    if (exp.getMoyenne() == moyEgalite && listExp.size() > NOMBRE_EXPOSE_SELECTION)
                    {
                        exp.setEtat(Etat.ATTENTE);                   
                    }
                    else
                    {
                        exp.setEtat(Etat.ACCEPTE);                     
                    }
                }
                else
                {
                    // Les exposés non retenus sont passés en état "Refusé"
                    exp.setEtat(Etat.REFUSE);
                    eDao.majEtat(exp);
                }    
            }
            
            session.setAttribute("lstExpose", listExp);
            req.setAttribute("page", lien);
            
            req.getRequestDispatcher("indexCo.jsp").forward(req, resp);
        }
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException
    {
        HttpSession session = req.getSession();
        
        String action = req.getParameter("action");
        
        if (action != null && "Annuler".equals(action))
        {
            // On supprime le colloque de la session
            session.removeAttribute("colloque");
            // On supprime la liste des exposés de la session
            session.removeAttribute("lstExpose");
            
            Link lien = Link.LISTE_PROGRAMME_A_DEFINIR;
            resp.sendRedirect(lien.getLien());
        }
        else
        {
            String dateDeb = req.getParameter("dtDebut");
            String dateFin = req.getParameter("dtFin");
            String[] choix = req.getParameterValues("choix");
            
            boolean erreur = false;
            List<String> listErr = new ArrayList<String>();
            
            Colloque co = (Colloque) session.getAttribute("colloque");
            List<Expose> listExp = (List<Expose>) session.getAttribute("lstExpose");

            // Récupère le dernier exposé de la liste pour avoir la moyenne basse
            Expose eMoyenne = listExp.get(listExp.size() - 1);
            
            // Si la liste des exposés retenus pour la programme est egal a 5
            // pas de choix du président donc pas besoin de faire de contrôle 
            // sur le choix
            if (listExp.size() > NOMBRE_EXPOSE_SELECTION)
            {
                if (choix == null || choix.length == 0)
                {
                    erreur = true;
                    listErr.add(ERR_CHOIX_ABS);
                }
                else
                {
                    int nbSelectionner = getNbSelectionner(listExp, eMoyenne.getMoyenne());
                    if (nbSelectionner + choix.length < NOMBRE_EXPOSE_SELECTION)
                    {
                        erreur = true;
                        int nbSelAbs = NOMBRE_EXPOSE_SELECTION - nbSelectionner;
                        listErr.add("Vous devez sélectionner " + nbSelAbs + " exposé(s).");
                    }
                    else if (nbSelectionner + choix.length > NOMBRE_EXPOSE_SELECTION)
                    {
                        erreur = true;
                        listErr.add("Il ne peut pas y avoir plus de " + NOMBRE_EXPOSE_SELECTION + " sélectionnés");
                    }
                    else
                    {
                        for (Expose exp : listExp)
                        {
                            if (exp.getMoyenne() == eMoyenne.getMoyenne())
                            {
                                boolean trouve = false;
                                for (String selection : choix)
                                {
                                    int idSel = Integer.parseInt(selection);
                                    
                                    if (exp.getId() == idSel)
                                    {
                                        exp.setEtat(Etat.ACCEPTE);
                                        trouve = true;
                                    }
                                }
                                
                                if (!trouve)
                                {
                                    exp.setEtat(Etat.ATTENTE);
                                }
                            }
                        }
                    }
                }
            }
            if (dateDeb == null || "".equals(dateDeb))
            {
                // Date de debut non saisie
                erreur = true;
                listErr.add(ERR_DEBUT_ABS);
            }
            else
            {
                SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
                try
                {
                    Date dtDebut = df.parse(dateDeb);
                    co.setDateDebut(dtDebut);
                }
                catch (ParseException pe)
                {
                    // Mauvais format de la date de début
                    erreur = true;
                    listErr.add(ERR_DEBUT_FORMAT);
                }
            }
            
            if (dateFin == null || "".equals(dateFin))
            {
                // Erreur date non saisie
                erreur = true;
                listErr.add(ERR_FIN_ABS);
            }
            else
            {
                SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
                try
                {
                    Date dtFin = df.parse(dateFin);
                    
                    if (co.getDateDebut() != null && co.getDateDebut().after(dtFin))
                    {
                        // Erreur la date de fin est postérieure a la date de début
                        erreur = true;
                        listErr.add(ERR_FIN_AVANT_DEBUT);
                    }
                    else
                    {
                        co.setDateFin(dtFin);
                    }
                }
                catch (ParseException pe)
                {
                    // Erreur mauvais format de date
                    erreur = true;
                    listErr.add(ERR_FIN_FORMAT);
                }
            }
            
            if (erreur)
            {
                // il y a des erreurs donc on retourne sur le formulaire
                Link lien = Link.FORM_PROGRAMME_A_VALIDER;
                
                session.setAttribute("colloque", co);
                req.setAttribute("page", lien);
                req.setAttribute("listErr", listErr);
                req.getRequestDispatcher("indexCo.jsp").forward(req, resp);
            }
            else
            {
                ExposeDao eDao = new ExposeDao();
                // Il y a pas d'erreur donc on enregistre le choix de l'exposé
                for (Expose e : listExp)
                {
                    if (e.getEtat().equals(Etat.ATTENTE))
                    {
                        e.setEtat(Etat.REFUSE);
                    }
                    
                    eDao.majEtat(e);
                }

                // On enregistre les modifications du colloque
                ColloqueDao cDao = new ColloqueDao();
                cDao.update(co);

                // On supprime le colloque de la session
                session.removeAttribute("colloque");
                // On supprime la liste des exposés de la session
                session.removeAttribute("lstExpose");
                
                Link lien = Link.LISTE_PROGRAMME_A_DEFINIR;
                resp.sendRedirect(lien.getLien());
            }
        }
    }

    /**
     * Récupère le nombre d'exposés sélectionnés
     *
     * @param listExp liste des exposés
     * @param moyenne moyenne d'égalité
     * @return
     */
    private int getNbSelectionner(List<Expose> listExp, float moyenne)
    {
        int nbSel = 0;
        
        for (Expose exp : listExp)
        {
            if (exp.getEtat().equals(Etat.ACCEPTE) && exp.getMoyenne() > moyenne)
            {
                nbSel++;
            }
        }
        
        return nbSel;
    }
}
